﻿using System;
using System.Collections.Generic;
using UnityEngine;
using Newtonsoft.Json;
using System.IO;

namespace PathFinding
{
    public class PathFindingAgent : MonoBehaviour
    {
        [Header("如果有mapInfo则用mapInfo初始化")]
        public UnityEngine.Object mapInfo;
        private Grid grid;
        public Transform startPoint;
        public Transform endPoint;
        private List<Cell> path = new List<Cell>();
        public int col = 100;
        public int row = 110;
        public int cellSize = 1;

        private ISeeker JPSSeeker;
        private ISeeker AStarSeeker;
        private void Start()
        {
            if (mapInfo != null)
            {
                string str = mapInfo.ToString();
                JPSMapConfig jpsConfig = JsonConvert.DeserializeObject<JPSMapConfig>(str);

                int len = jpsConfig.unWalkables.Count;
                int[] unwalkX = new int[len];
                int[] unwalkY = new int[len];
                for (int i = 0; i < len; i++)
                {
                    unwalkX[i] = jpsConfig.unWalkables[i].x;
                    unwalkY[i] = jpsConfig.unWalkables[i].y;
                }
                grid = new Grid(0, 0, jpsConfig.row, jpsConfig.col, 1, unwalkX, unwalkY);
            }
            else
            {
                int startX = 0;
                int startY = 0;
                int[] unwalkX = new int[5] { 3, 4, 5, 6, 7 };
                int[] unwalkY = new int[5] { 4, 4, 4, 4, 4 };
                //this.grid = new Grid(startX, startY, col, row, cellSize, unwalkX, unwalkY);
                this.grid = new Grid();
                StartCoroutine(this.grid.initAsync(startX, startY, col, row, cellSize, unwalkX, unwalkY));
            }
            JPSSeeker = new JPSSeeker(this.grid);
            AStarSeeker = new AStarSeeker(this.grid);
        }

        public void OnGUI()
        {
            if (GUILayout.Button("AStar寻路", GUILayout.Height(40), GUILayout.Width(100)))
            {
                if (startPoint != null && endPoint != null)
                {
                    Vector2 startPos = new Vector2(startPoint.position.x, startPoint.position.z);
                    Vector2 endPos = new Vector2(endPoint.position.x, endPoint.position.z);
                    path = AStarSeeker.findPath(startPos, endPos);
                }
            }
            if (GUILayout.Button("JPS寻路", GUILayout.Height(40), GUILayout.Width(100)))
            {
                if (startPoint != null && endPoint != null)
                {
                    Vector2 startPos = new Vector2(startPoint.position.x, startPoint.position.z);
                    Vector2 endPos = new Vector2(endPoint.position.x, endPoint.position.z);
                    path = JPSSeeker.findPath(startPos, endPos);
                }
            }

            GUILayout.Space(30);
            if (GUILayout.Button("清理路径", GUILayout.Height(100), GUILayout.Height(35)))
            {
                this.path.Clear();
            }
            GUILayout.Space(10);
            GUILayout.Label("Map名称:");
            mapName = GUILayout.TextField(mapName, GUILayout.Height(100), GUILayout.Height(35));
            if (GUILayout.Button("保存Map", GUILayout.Height(100), GUILayout.Height(35)))
            {
                if (string.IsNullOrEmpty(mapName))
                {
                    Debug.LogError("请输入map名称");
                    return;
                }
                JPSMapConfig jpsConfig = new JPSMapConfig();
                jpsConfig.cellSize = grid.cellSize;
                jpsConfig.row = grid.row;
                jpsConfig.col = grid.col;
                jpsConfig.unWalkables = new List<UnWalkableIndex>();
                for (int x = 0; x < grid.row; x++)
                {
                    for (int y = 0; y < grid.col; y++)
                    {
                        Cell cell = grid[x, y];
                        if (!cell.isWalkable)
                        {
                            UnWalkableIndex unWalkable = new UnWalkableIndex();
                            unWalkable.x = x;
                            unWalkable.y = y;
                            jpsConfig.unWalkables.Add(unWalkable);
                        }
                    }
                }
                saveJson(jpsConfig, Path.Combine(Application.dataPath, string.Format("ZTest/PathFinding/{0}.txt", mapName)));
            }
        }

        #region 制作地图
        private string mapName = "map001";
        public void saveJson(object obj, string path)
        {
            string txt = JsonConvert.SerializeObject(obj);
            File.WriteAllText(path, txt);
        }

        private GameObject mouseLayerBox;
        private int goalIndex = -1;
        private Vector3 oldPos;
        private void Update()
        {
            if (Input.GetMouseButton(1))
            {
                if (mouseLayerBox == null)
                {
                    mouseLayerBox = new GameObject("mouseLayerBox");
                    BoxCollider box = mouseLayerBox.AddComponent<BoxCollider>();
                    box.size = new Vector3(1000, 0.1f, 1000);
                }
                Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
                RaycastHit hit;
                if (Physics.Raycast(ray, out hit))
                {
                    Cell cell = this.grid.getCellByPos(new Vector3(hit.point.x, 0, hit.point.z));
                    if (cell != null)
                    {
                        cell.isWalkable = false;
                    }
                }
            }
            if (Input.GetMouseButton(0))
            {
                if (mouseLayerBox == null)
                {
                    mouseLayerBox = new GameObject("mouseLayerBox");
                    BoxCollider box = mouseLayerBox.AddComponent<BoxCollider>();
                    box.size = new Vector3(1000, 0.1f, 1000);
                }
                Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
                RaycastHit hit;
                if (Physics.Raycast(ray, out hit))
                {
                    Cell cell = this.grid.getCellByPos(new Vector3(hit.point.x, 0, hit.point.z));
                    if (cell != null)
                    {
                        cell.isWalkable = true;
                    }
                }
            }
        }
        #endregion


        private void OnDrawGizmos()
        {
            if (this.grid != null)
            {
                this.grid.draw();
            }
            drawPath();
        }
        private void drawPath()
        {
            if (this.path != null && this.path.Count > 0)
            {
                for (int i = 0; i < path.Count; i++)
                {
                    Cell cell = path[i];
                    Vector3 pos = grid.getPosByIndex(cell.x, cell.y);
                    Gizmos.color = Color.green;
                    Grid.drawBox(pos);
                    if (i + 1 < path.Count)
                    {
                        Cell nextCell = path[i + 1];
                        Grid.drawLine(grid.getPosByIndex(cell.x, cell.y), grid.getPosByIndex(nextCell.x, nextCell.y));
                    }
                }
            }

            //var ier = closeSet.GetEnumerator();
            //while (ier.MoveNext())
            //{
            //    Cell cell = ier.Current;
            //    Vector3 pos = grid.getPosByIndex(cell.x, cell.y);
            //    Gizmos.color = Color.blue;
            //    Grid.drawBox(pos);
            //}

            //var ier2 = openSet.GetEnumerator();
            //while (ier2.MoveNext())
            //{
            //    Cell cell = ier2.Current;
            //    Vector3 pos = grid.getPosByIndex(cell.x, cell.y);
            //    Gizmos.color = Color.yellow;
            //    Grid.drawBox(pos);
            //}

        }

    }

}
